package dk.mirasola.systemtraining.user.client.ui.wizard;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.Widget;

import java.util.ArrayList;
import java.util.List;

public abstract class Wizard extends Composite {
    interface WizardUiBinder extends UiBinder<Widget,Wizard>{}
    private static WizardUiBinder uiBinder = GWT.create(WizardUiBinder.class);

    @UiField
    FlowPanel progressPanel;
    @UiField
    LayoutPanel stepPanel;
    @UiField
    Button next;
    @UiField
    Button back;
    @UiField
    Button finish;
    @UiField
    Button cancel;

    private int currentStep = 0;
    private List<WizardStep> wizardSteps = new ArrayList<WizardStep>();

    public Wizard() {
        initWidget(uiBinder.createAndBindUi(this));

        initBackButton();
        initNextButton();
        initFinishButton();
        initCancelButton();
    }

    private void initCancelButton() {
        cancel.setText("Cancel");
        cancel.setEnabled(true);
        cancel.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                next.setEnabled(false);
                cancel.setEnabled(false);
                finish.setEnabled(false);
                back.setEnabled(false);
            }
        });
    }

    private void initFinishButton() {
        finish.setText("Finish");
        finish.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                next.setEnabled(false);
                cancel.setEnabled(false);
                finish.setEnabled(false);
                back.setEnabled(false);
            }
        });
        finish.setEnabled(false);
    }

    private void initNextButton() {
        next.setText("Next");
        next.setEnabled(false);
        next.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (currentStep >= wizardSteps.size() - 1) {
                    return;
                }
                currentStep++;
                updateWizard();
            }
        });
    }

    private void initBackButton() {
        back.setText("Back");
        back.setEnabled(false);
        back.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (currentStep == 0) {
                    return;
                }
                currentStep--;
                updateWizard();
            }
        });
    }

    protected void setCurrentStep(int index) {
        if (index < 0 || index > wizardSteps.size() - 1) {
            throw new IndexOutOfBoundsException();
        }
        currentStep = index;
        updateWizard();
    }

    private void updateButtonPanel() {
        back.setEnabled(false);
        next.setEnabled(false);
        finish.setEnabled(false);

        back.setVisible(currentStep > 0);
        next.setVisible(currentStep < wizardSteps.size() - 1);
        finish.setVisible(currentStep == wizardSteps.size() - 1);
    }

    protected void addWizardStep(WizardStep wizardStep) {
        wizardSteps.add(wizardStep);
        progressPanel.add(new InlineHTML(wizardStep.getProgressText()));
    }

    protected void onLoad() {
        updateWizard();
    }

    private void updateWizard() {
        updateButtonPanel();
        WizardStep current = wizardSteps.get(currentStep);
        progressPanel.clear();
        for (int i = 0 ; i < wizardSteps.size() ; i++) {
            WizardStep wizardStep = wizardSteps.get(i);
            HTML html = new HTML(wizardStep.getProgressText());
            html.setStyleName("wizardProgress");
            if (wizardStep == current) {
                html.addStyleDependentName("current");
            }
            progressPanel.add(html);
            if (i < wizardSteps.size() - 1) {
                HTML arrowDown = new HTML(SafeHtmlUtils.fromTrustedString("&darr;"));
                arrowDown.setStyleName("wizardProgress");
                progressPanel.add(arrowDown);
            }
        }
        stepPanel.clear();
        stepPanel.add(current.getWidget());
        current.activate();
    }

    protected Button getNext() {
        return next;
    }

    protected Button getBack() {
        return back;
    }

    protected Button getCancel() {
        return cancel;
    }

    protected Button getFinish() {
        return finish;
    }

    protected int getStepsCount() {
        return wizardSteps.size();
    }
}
